// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#pragma once

#include <vector>
#include "melon/executor.h"

namespace kumo::pollux::dwio::common {
    /*
     * A helper class that allows to run a function on a range of indices in
     * multiple threads.
     * The range (from, to] is split into equal-sized chunks and each chunk is
     * scheduled in a different thread. The number of threads is: parallelismFactor
     * It means that if parallelismFactor == 1 (or 0), the function will be executed
     * in the calling thread for the entire range. If parallelismFactor == 2, the
     * function will be called for half of the range in one thread in the executor,
     * and for the last half in the calling thread (and so on). If no executor is
     * passed (nullptr), the function will be executed in the calling thread for the
     * entire range.
     */
    class ParallelFor {
    public:
        ParallelFor(
            melon::Executor::KeepAlive<> executor,
            size_t from, // start index
            size_t to, // past end index
            // number of threads.
            size_t parallelismFactor);

        ParallelFor(
            std::shared_ptr<melon::Executor> executor,
            size_t from, // start index
            size_t to, // past end index
            // number of threads
            size_t parallelismFactor);

        void execute(std::function<void(size_t)> func);

    private:
        std::shared_ptr<melon::Executor> owned_;
        melon::Executor::KeepAlive<> executor_;
        std::vector<std::pair<size_t, size_t> > ranges_;
    };
} // namespace kumo::pollux::dwio::common
